/**
 * @file useRegistField
 * @author  fanxl
 * @description 注册Field
 */
import {isArray, keyBy, keys} from 'lodash-es';
import {createFieldsModel} from '../field';
import {type ComputedRef, unref} from 'vue';
import type {UnionSpecItem} from '../interface';
import {useRegistOption} from './useRegistOption';
import type {UseForm} from './types';
import {createRandomChars} from './utils';

export const useRegistField = (
    spec: ComputedRef<Array<UnionSpecItem>> | Array<UnionSpecItem>,
    form: UseForm,
    parentPath: string = ''
) => {
    const {registerField, getFieldValue} = form;

    const regist = (spec: ComputedRef<Array<UnionSpecItem>> | Array<UnionSpecItem>, parentPath: string) => {
        unref(spec).forEach((specItem: UnionSpecItem, index: number) => {
            const fieldData = createFieldsModel(specItem, index, parentPath);
            const registerOption = useRegistOption(fieldData, form.values);
            const fieldName = fieldData.path;
            if (registerOption.isRemove) {
                return;
            }
            registerField(unref(fieldName), registerOption);

            const fieldValue = form.getFieldValue(unref(fieldName));
            if (isArray(fieldValue)) {
                const chars = (fieldValue || []).map(() => createRandomChars());
                form.setListChars(unref(fieldName), chars);
            }

            if (specItem.dataType === 'OBJECT' && specItem?.items?.length) {
                regist(specItem.items, fieldName);
            }

            if (specItem.dataType === 'LIST') {
                const listValue = getFieldValue(fieldName) as any[];
                const fakeSpecs = listValue.map((el, index) => {
                    return specItem.items
                        ? ({
                              name: `[${index}]`,
                              displayName: specItem.displayName,
                              dataType: 'OBJECT',
                              display: 'toggle-block',
                              items: specItem.items
                          } as UnionSpecItem)
                        : ({
                              ...specItem.element,
                              name: `[${index}]`
                          } as UnionSpecItem);
                });
                regist(fakeSpecs, fieldName);
            }

            if (specItem.dataType === 'ALTERNATIVE') {
                const childMap = keyBy(specItem.enumValues, 'value');
                const getChildKey = (data: any) => (typeof data === 'object' ? keys(data)[0] : undefined);
                const fieldValue = getFieldValue(fieldName);
                const childKey = getChildKey(fieldValue);
                if (childKey) {
                    const childSpec = childMap[childKey]?.items;
                    if (childSpec && childSpec.length) {
                        regist(childSpec, [fieldName, childKey].join('.'));
                    }
                }
            }
        });
    };

    regist(spec, parentPath);
};
